home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The PC-SIG Library 9
/
The PC-SIG Library on CD ROM - Ninth Edition.iso
/
001_100
/
DISK0070
/
DISK0070.ZIP
/
VPRINT.ASM
< prev
next >
Wrap
Assembly Source File
|
1983-02-13
|
8KB
|
230 lines
; PROGRAM VPRINT version 1.0
; by Dave Whitman
;
; Redirects printer output to a specified disk file,
; providing a virtual printer. Invoked from DOS by
; the command: VPRINT filespec
;
; Changes vector to BIOS printer routine to point
; to VPRINT code. The VPRINT code is grafted onto
; DOS, and will not be overwritten by other programs.
;
fcb equ [5CH] ;file control block
name equ [5DH] ;name field of fcb
name_length equ 11 ;length of name field in fcb
cur_block equ [68H] ;current block field
current_rec equ [7CH] ;current record field
record_size equ [6AH] ;record size field
dta_length equ 200H ;length of internal disk buffer
param_count equ [80H] ;contains # of chars in param area
param_area equ [81H] ;PSP unformated param area
dummy_dta equ [80H] ;leave dta set here on return
cr equ 0DH ;ascii carriage return
lf equ 0AH ;ascii line feed
vector_offset equ [005CH] ;offset part of interrupt vector 17H
vector_segment equ [005EH] ;segment part of interrupt vector 17H
printer_io equ EFD2H ;offset of BIOS routine
;
jmp init ;branch around redirection code
;
;------------------------------------------------------
; This section of code will be grafted onto DOS.
; Calls to PRINTER_IO are redirected here, where
; they are converted to DOS sequential file writes.
;
convert
sti ;enable interupts
or ah,ah ;request to print char?
jnz abort ;abort if not
;
push dx ;save state
push ds
push cs
pop ds ;and establish addr.
mov char,al ;save the char
;
cmp al,lf ;is this a line feed?
je exit ;exit if so
;
call printchar ;print the charactor
cmp al,cr ;was that a carriage return?
jne exit ;exit if not
mov al,lf ;otherwise generate a line feed
call printchar ;and send it
;
exit mov al,char ;restore state
pop ds
pop dx
;
;=========================================================
; We have to return a status byte in AH. The way I read
; Tech. Ref., to signal all ok we should send value 50H.
; However, a long DEBUG session showed that Easywriter 1.1
; expects to get 90H as the OK value. I would interpret this
; as "printer busy", but we'll humor Easywriter.
;=========================================================
;
abort mov ah,90H ;move status = ok to AH
iret ;and return
;
printchar proc near
push di
mov di,numchars ;position in buffer for char
mov offset(dta)[di],al ;mov char into buffer
;
inc di ;update number of chars
mov numchars,di ;and save it
;
cmp di,dta_length ;is the buffer full?
jne pc-exit ;exit if not
call dumpdta ;otherwise dump it
;
pc-exit pop di
ret
endp
;
dumpdta proc near
push ax ;save state
push dx
;
mov ah,0FH ;open file
mov dx,offset(fcb)
int 21H
;
movw record_size,dta_length ;set record size
mov ax,block_save ;set fcb current block
mov cur_block,ax
;
mov dx,offset(dta) ;set disk transfer addr.
mov ah,1AH
int 21H
;
mov dx, offset(fcb) ;write buffer to disk
mov ah,15H
int 21H
;
mov ax, cur_block ;save current block
mov block_save,ax
;
mov ax,1000H ;close file
mov dx,offset(fcb)
int 21H
;
movw numchars,0000H ;buffer is now empty
;
;======================================================
; Since we don't know where the DTA was set upon entry,
; we can't really restore the state of the machine.
; What we'll do is set up a dummy DTA for the caller to
; use, so it doesn't clobber our buffered data between calls.
; This is *NOT* foolproof, but seems to work OK with Easywriter.
;======================================================
;
mov dx,offset(dummy_dta) ;set DTA to dummy block
mov ah,1AH
int 21H
pop dx ;restore state
pop ax
ret ;and return
endp
;
;====================================================
; Data area for resident section
;====================================================
char db 00H ;to save the char. passed
numchars db 00H,00H ;word: # of chars in buffer
block_save db 00H,00H ;to save current block between calls
dta ds dta_length ;internal data buffer
;
;===================================================
; Initialization section. Does not become resident.
;===================================================
init cmpb name,' ' ;was a file specified?
jnz a1 ;skip if so
cmpb param_count,00H ;any param chars?
jz default ;skip if not
xor ch,ch ;set up for scan
mov cl,param_count
mov di,offset(param_area)
mov al,'/' ;look for '/'
repnz ;scan to end or 1st match
scasb
;
jnz default ;skip if not found
xorb [di],20H ;guarantees upper case
;
cmpb [di],'N' ;is it an N?
je p_handler ;if so, jump
;
;if no parameters decoded, just fall through
;and set up print file with default name
;
default mov si, offset(default_file_name)
mov di, offset(name)
mov cx, name_length
rep
movsb
;
a1 mov dx, offset(fcb) ;check if file exists
mov ah,11H
int 21H
;
test al,al ;file found?
jnz a2 ;skip if not
;
mov dx, offset(err_msg_1) ;otherwise print
mov ah,09H ;error message
int 21H
int 20H ;and return to DOS
;
a2 mov ah,16H ;create file
int 21H
;
test al,al ;file created?
jz a3 ;skip if so
mov dx, offset(err_msg_2) ;otherwise error
mov ah, 09H
int 21H
int 20H
;
a3 movw current_rec, 0 ;fill in fcb
;
mov ah,10H ;close file
mov dx, offset(fcb)
int 21H
;
mov ax,2517H ;reset printer vector
mov dx, offset(convert)
int 21H
;
mov dx,offset(init) ;point dx past resident code
int 27H ;end but stay resident
;===================================================================
p_handler
;
mov ax,0000H ;ext. addr. for vector
mov ds,ax
;
cmpw vector_offset,printer_io ;already in BIOS?
je p_exit ;exit if so
;
mov ds,vector_segment ;est. addr. in original vprint seg
call dumpdta ;operates on buffer in original vprint
;
mov ax,F000H ;reset vector 17H to BIOS routine
mov ds,ax ;bios segment
mov dx,printer_io ;printer support routine
mov ax,2517H
int 21H
;
p_exit int 20H ;return to DOS
;
;===================================================================
err_msg_1 db 'File already exists!$'
err_msg_2 db 'No room for file in directory.$'
default_file_name db 'VIRTUAL PRN'